import { type GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { type World } from "../world/World";
import { LoadingTrackerEntry } from "./LoadingTrackerEntry";
import { UIManager } from "./UIManager";


export class LoadingManager {

    public firstLoad = true;
    public onFinishedCallback: () => void;

    private world: World;
    private gltfLoader: GLTFLoader;
    private loadingTracker: LoadingTrackerEntry[] = [];

    constructor ( world: World ) {
        this.world = world;
        this.gltfLoader = new GLTFLoader();

        this.world.setTimeScale( 0 );

        UIManager.setUserInterfaceVisible( false );
        UIManager.setLoadingScreenVisible( true );
    }

    public loadGLTF ( path: string, onLoadingFinished: ( gltf: GLTF ) => void ) {

        const trackerEntry = this.addLoadingEntry( path );

        this.gltfLoader.load(
            path,
            ( gltf ) => {
                onLoadingFinished( gltf );
                this.downLoading( trackerEntry );
            },
            ( xhr ) => {
                if ( xhr.lengthComputable ) {
                    trackerEntry.progress = xhr.loaded / xhr.total;
                }
            },
            ( error ) => {
                console.error( error );
            }
        );
    }

    public addLoadingEntry ( path: string ) {
        const entry = new LoadingTrackerEntry( path );
        this.loadingTracker.push( entry );
        return entry;
    }

    private downLoading ( trackerEntry: LoadingTrackerEntry ) {
        trackerEntry.finished = true;
        trackerEntry.progress = 1;

        if ( this.isLoadingDown() ) {
            if ( this.onFinishedCallback !== undefined ) {
                this.onFinishedCallback();
            } else {
                UIManager.setUserInterfaceVisible( true );
            }
            UIManager.setLoadingScreenVisible( false );
        }
    }

    private isLoadingDown () {
        this.loadingTracker.forEach( entry => {
            if ( entry.finished === false ) return false;
        } );
        return true;
    }
}